package utilities;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import dataFromXml.Attribute;
import dataFromXml.Eigenvalue;
import dataFromXml.ResultLimit;

public class ResultLimitHandler {

	public static void AttributeMRFile(String tFolder, String frameFolder,
			Map<String, String> nameToType, String attributesList,
			List<Eigenvalue> eigenList, ResultLimit rlNode) {
		// TODO Auto-generated method stub
		String filePath = tFolder + File.separator + "MR_ResultLimitMapper" + ".java";
		
		// if there is no target file, create it.
		BufferedWriter bw;
		BufferedReader br;
		try {
			bw = new BufferedWriter(new FileWriter(filePath));
			br = new BufferedReader(new FileReader(frameFolder + "ResultLimitT"));
			
			String line;
			String[] strArray;
			
			while ((line = br.readLine()) != null) {
				
				strArray = line.split("#");
				if (strArray.length > 1) {
					if (strArray[1].equals("0")) {
						String[] pathFolder = tFolder.split("/");
						strArray[1] = pathFolder[pathFolder.length - 1];
					} else if (strArray[1].equals("1")) {
						strArray[1] = getAllFunctions(rlNode);
					} else if (strArray[1].equals("2")) {
						strArray[1] = rlNode.getAttrList().size() + "";
					} else if (strArray[1].equals("3")) {
						strArray[1] = getAllExp(rlNode, nameToType, attributesList, eigenList);
					}
				}
				
				line = "";
				for (int i = 0; i < strArray.length; i++) {
					line += strArray[i];
				}
				bw.write(line + "\n");
				bw.flush();
			}
			bw.write("\n");
			bw.flush();

			bw.close();
			br.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			bw = null;
			br = null;
		}
	}
	
	private static String getExp(Attribute attr, Map<String, String> nameToType, 
			String attributesList, List<Eigenvalue> eigenList) {
		// TODO Auto-generated method stub
		
		String tempFormula;
		
	//	String[] attributes = attributesList.split(" ");
		String[] attributes = getSortAttrList(attributesList);
		int[] sortNum = getSortNumberOfAttrs(attributes, attributesList);
		String attrExpression = attr.getAttrExpression();
		for (int i=0; i<eigenList.size(); i++) {
			
			if (attrExpression.contains(eigenList.get(i).getEigenName())) {
				
				if (nameToType.get(eigenList.get(i).getEigenAttr()).equals("int")) {
				
					tempFormula = "Integer.valueOf(amma.get(\"" + eigenList.get(i).getEigenName() + "\"))"; 
					attrExpression = attrExpression.replace(eigenList.get(i).getEigenName(), tempFormula);
					
				} else if (nameToType.get(eigenList.get(i).getEigenAttr()).equals("double")) {
				
					tempFormula = "Double.valueOf(amma.get(\"" + eigenList.get(i).getEigenName() + "\"))"; 
					attrExpression = attrExpression.replace(eigenList.get(i).getEigenName(), tempFormula);
					
				} else {
					assert false : "Attribute expression may be error!";
				}
			}
		}
		for (int i=0; i<attributes.length; i++) {
			
			if (attrExpression.contains(attributes[i])) {
				
				if (nameToType.get(attributes[i]).equals("int")) {
					
					tempFormula = "Integer.valueOf(strArray[" + sortNum[i] + "])";
					attrExpression = attrExpression.replace(attributes[i], tempFormula);

				} else if (nameToType.get(attributes[i]).equals("double")) {
					
					tempFormula = "Double.valueOf(strArray[" + sortNum[i] + "])";
					attrExpression = attrExpression.replace(attributes[i], tempFormula);
					
				} else {
					
					tempFormula = "strArray[" + sortNum[i] + "]";
					attrExpression = attrExpression.replace(attributes[i], tempFormula);
					
				}
			}
		}
		return attrExpression;
	}

	private static int[] getSortNumberOfAttrs(String[] attributes,
			String attributesList) {
		// TODO Auto-generated method stub
		String[] originalAttrList = attributesList.split(" ");
		int[] sortNum = new int[attributes.length];
		for (int i=0; i<attributes.length; i++) {
			for (int j=0; j<originalAttrList.length; j++) {
				if (originalAttrList[j].equals(attributes[i])) {
					sortNum[i] = j;
				}
			}
		}
		return sortNum;
	}

	private static String[] getSortAttrList(String attributesList) {
		// TODO Auto-generated method stub
		String[] originalAttrList = attributesList.split(" ");
		String targetAttrList = "";
		ArrayList<String> attrList = new ArrayList<>();
		attrList.add("#");
		for (int i=0; i<originalAttrList.length; i++) {
			for (int j=0; j<attrList.size(); j++) {
				if (originalAttrList[i].length() >= attrList.get(j).length()) {
					attrList.add(j, originalAttrList[i]);
					break;
				}
			}
		}
		
		for (int i=0; i<attrList.size()-1; i++) {
			targetAttrList += attrList.get(i) + " ";
			System.out.println(attrList.get(i) + " ");
		}
		return targetAttrList.split(" ");
	}

	private static String getAllExp(ResultLimit rlNode,	Map<String, String> nameToType,
			String attributesList, List<Eigenvalue> eigenList) {
		// TODO Auto-generated method stub
		List<Attribute> attrList = rlNode.getAttrList();
		StringBuilder sb = new StringBuilder();
		String temp;
		
		for (int i=0; i<attrList.size(); i++) {
			temp = "resultList[" + i + "] = String.valueOf(" + getExp(attrList.get(i), nameToType, attributesList, eigenList) + ");";
			sb.append("\t\t" + temp + "\n");
		}
		
		return sb.toString();
	}

	/*
	 * get all function in attributes' node and return the string of the list of functions
	 */
	private static String getAllFunctions(ResultLimit rlNode) {
		// TODO Auto-generated method stub
		List<Attribute> attrList = rlNode.getAttrList();
		StringBuilder sb = new StringBuilder();
		String temp;
		
		for (int i=0; i<attrList.size(); i++) {
			temp = attrList.get(i).getFunction();
			if (temp.length() != 0)
				sb.append(temp + "\n");
		}
		return sb.toString();
	}

	public static void AttributeProfile(String tFolder, String frameFolder, int jobNum) {
		// TODO Auto-generated method stub
		BufferedWriter bw;
		BufferedReader br;
		try {
			bw = new BufferedWriter(new FileWriter(tFolder + File.separator + "tempProfile", true));
			br = new BufferedReader(new FileReader(frameFolder + "ResultLimitP"));

			String line;

			while ((line = br.readLine()) != null) {

				String[] strArray = line.split("#");
				if (strArray.length > 1) {
					if (strArray[1].equals("0")) {
						strArray[1] = jobNum + "";
						line = strArray[0] + strArray[1] + strArray[2];
					} else {
						assert false : "Result limitation profile may be error!";
					}
				}
				bw.write(line + "\n");
				bw.flush();
			}
			bw.write("\n");
			bw.flush();

			bw.close();
			br.close();
			System.out.println("Result limitation profile is OK!");
		} catch (IOException ex) {
			ex.printStackTrace();
		}
	}
}
